<?php

namespace app\load\service;

use app\load\loadModel\OaModel;
use app\load\model\oa\ApproveModel;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\facade\Db;
use think\Model;

/**
 * oa业务模块
 */
class OaService
{


    /**
     * 添加任务
     * @param $param | 数据
     * @param $uid | 用户id
     * @param $did | 用户bu
     */
    public function save($param, $uid, $did): bool
    {
        try {

            $flow_list = Db::name('Flow')->where('id', $param['flow_id'])
                ->field('flow_list,is_sign')->find();
            $flow = unserialize($flow_list['flow_list']);
            $param['is_sign'] = $flow_list['is_sign'];
            //修改
            if (!empty($param['id']) and $param['id'] > 0) {
                $this->updateTask($param, $uid, $flow);
            }
            //添加
            if (empty($param['id'])) {
                $this->addTask($param, $uid, $flow, $did);
            }

            return true;
        } catch (Exception $exception) {
            throw $exception;
        }
    }


    /**
     * 更新任务
     * @param $param | Data
     * @param $uid | User ID
     * @throws DbException
     */
    public function updateTask($param, $uid, $flow)
    {
        $param['update_time'] = time();
        $param['check_status'] = 0;
        $param['check_step_sort'] = 0;

        //采购单独处理
        if ($param['type'] == 15) {
            $product_data = $this->productPackage($param['product_sn'], $param['num'], $param['remarks'], $param['id']);
            // 使用事务进行删除和插入操作
            Db::transaction(function () use ($param, $product_data) {
                Db::name('PurchaseProduct')->where('approve_id', $param['id'])->delete();
                Db::name('PurchaseProduct')->insertAll($product_data);
            });
        }

        // 删除已有的审批流程和审批记录
        Db::transaction(function () use ($param) {
            Db::name('FlowStep')->where(['action_id' => $param['id'], 'type' => 1])->update(['delete_time' => time()]);
            Db::name('FlowRecord')->where(['action_id' => $param['id'], 'type' => 1])->update(['delete_time' => time()]);
        });

        // 更新审批流程和审批记录
        Db::transaction(function () use ($param, $flow, $uid) {
            if (!isset($param['check_admin_ids'])) {
                $param['check_admin_ids'] = $this->getCheckAdminIds($flow[0]['flow_type'], $uid, $flow);
                Db::name('Approve')->where('id', $param['id'])->strict(false)->field(true)->update($param);
                $flowSteps = [];
                foreach ($flow as $key => &$value) {
                    $value['action_id'] = $param['id'];
                    $value['sort'] = $key;
                    $value['create_time'] = time();
                    $flowSteps[] = $value;
                }

                Db::name('FlowStep')->strict(false)->field(true)->insertAll($flowSteps);
            } else {
                Db::name('Approve')->where('id', $param['id'])->strict(false)->field(true)->update($param);
                $flow_step = [
                    'action_id' => $param['id'],
                    'flow_uids' => $param['check_admin_ids'],
                    'create_time' => time()
                ];
                Db::name('FlowStep')->strict(false)->field(true)->insertGetId($flow_step);
            }
        });


        // 添加提交记录
        $this->submitApplication($param['id'], $uid, $param['type'], $param['check_admin_ids'] ?? '', $param, '重新提交申请');

    }


    /**
     * 添加任务
     * @param $param | Data
     * @param $uid | User ID
     * @param $flow | 审核流
     * @param $did | 部门
     * @throws Exception
     */
    public function addTask($param, $uid, $flow, $did)
    {
        $param['admin_id'] = $uid;
        $param['department_id'] = $did;
        $param['create_time'] = time();
        $param['check_admin_ids'] = !isset($param['check_admin_ids']) ? $this->getCheckAdminIds($flow[0]['flow_type'], $uid, $flow) : $param['check_admin_ids'];

        //添加审批信息
        $aid = OaModel::Approve()->add($param);
//        $aid = 1;
        if ($flow) {
            foreach ($flow as $key => &$value) {
                $value['action_id'] = $aid;
                $value['sort'] = $key;
                $value['create_time'] = time();
            }
        } else {
            $flow = [
                [
                    'action_id' => $aid,
                    'flow_uids' => $param['check_admin_ids'],
                    'create_time' => time()
                ]
            ];
        }
//        print_r($flow);die;
        Db::name('FlowStep')->strict(false)->field(true)->insertAll($flow);

        //采购单独处理
        if ($param['type'] == 15) {
            $product_data = $this->productPackage($param['product_sn'], $param['num'], $param['remarks'], $aid);
            //添加采购信息
            Db::name('PurchaseProduct')->strict(false)->field(true)->insertAll($product_data);
        }

        //添加提交记录
        $this->submitApplication($aid, $uid, $param['type'], $param['check_admin_ids'], $param, '提交申请');
    }


    /**
     * 提交申请并发送通知
     * @param int $actionId
     * @param int $userId
     * @param int $type
     * @param  $checkAdminIds
     * @param array $param
     * @param string $content
     */
    protected function submitApplication(int $actionId, int $userId, int $type, $checkAdminIds, array $param, string $content)
    {
        // 添加提交记录
        $checkData = [
            'action_id' => $actionId,
            'check_user_id' => $userId,
            'content' => $content,
            'check_time' => time(),
            'create_time' => time()
        ];
        Db::name('FlowRecord')->strict(false)->field(true)->insertGetId($checkData);

        $param['uid'] = $userId;
        api_add_log('edit', $actionId, $param);

        // 向审批者发送通知
        $msg = [
            'from_uid' => $userId,
            'title' => Db::name('FlowType')->where('id', $type)->value('title'),
            'action_id' => $actionId
        ];

        $users = $checkAdminIds ?? '';

        sendMessage($users, 21, $msg);
    }


    /**
     * 基于流类型获取check admin id的常用方法
     * @param $flowType | 类型
     * @param $userId | 用户id
     * @return mixed
     * @throws Exception
     */
    protected function getCheckAdminIds($flowType, $userId, $flow)
    {
        switch ($flowType) {
            case 1:
                // 部门负责人
                $leader = get_department_leader($userId);
                if ($leader == 0) {
                    throw new Exception('审批流程设置有问题：当前部门负责人还未设置，请联系HR或者管理员');
                }
                break;
            case 2:
                // 上级部门负责人
                $leader = get_department_leader($userId, 1);
                if ($leader == 0) {
                    throw new Exception('审批流程设置有问题：上级部门负责人还未设置，请联系HR或者管理员');
                }
                break;
            default:
                if (isset($flow[0]) && isset($flow[0]['flow_uids'])) {
                    $leader = $flow[0]['flow_uids'];
                } else {
                    throw new Exception('审批流程设置有问题：流程UID未找到');
                }

                break;
        }

        return $leader;
    }


    /**
     * 商品信息组装
     * @param $product_sn | 商品单号
     * @param $num | 数量
     * @param $remarks | 备注
     * @param $approve_id | 流程id
     * @return array
     */
    public function productPackage($product_sn, $num, $remarks, $approve_id): array
    {
        $data = [];
        $time = time();
        for ($i = 0; $i < count($product_sn); $i++) {
            $values = explode('!!', $product_sn[$i]);
            $item = [
                'product_sn' => $values[0] ?? '',
                'name' => $values[1] ?? '',
                'num' => $num[$i],
                'remarks' => $remarks[$i],
                'create_time' => $time,
                'approve_id' => $approve_id
            ];
            $data[] = $item;
        }
        return $data;
    }


    /**
     * 删除添加的商品
     * @param array $where
     * @return bool
     */
    public function delProduct(array $where = []): bool
    {
        return OaModel::PurchaseProduct()->where($where)->delete();
    }


    /**
     * 详情
     * @param array $where
     * @param string $filed
     * @return ApproveModel|array|mixed|Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function info(array $where , string $filed = '*' )
    {
       return OaModel::Approve()->info($where ,  $filed);
    }

}